﻿// Original author contact info: Owen Emlen (owene_1998@yahoo.com)
// Note: other individuals may also have contributed to this code
// Project hosted on CodePlex.com as of 1/10/2009 at http://wpfimageviewer.codeplex.com
using System;
using System.Threading;
using BrainTechLLC.ImageOperators;
using System.Diagnostics;
using System.Drawing;
using BrainTechLLC;
using BrainTechLLC.WPF;
using BrainTechLLC.ThreadSafeObjects;
using System.Windows;
using BrainTechLLC.ImageOperatorsNonAForgeDependent;
using System.IO;
using System.Drawing.Imaging;
using System.ComponentModel;

namespace ImageAppDataModels
{
    public partial class FileImage : BaseNotifyPropertyChangedUI, IHasThumbnail, IObjectLock
    {
        public static ThumbnailProvider ThumbnailProvider;
        public SingleThumbnail _ThumbnailObject;

        protected FastSmartWeakEvent<EventHandler> _thumbnailSet = new FastSmartWeakEvent<EventHandler>();
        public event EventHandler ThumbnailSet { add { _thumbnailSet.Add(value); } remove { _thumbnailSet.Remove(value); } }

        protected FastSmartWeakEvent<EventHandler<ObjectEventArgs<FileImage, ResizeInfo>>> _rotateResizeDone = new FastSmartWeakEvent<EventHandler<ObjectEventArgs<FileImage, ResizeInfo>>>();
        public event EventHandler<ObjectEventArgs<FileImage, ResizeInfo>> RotateOrResizeDone { add { _rotateResizeDone.Add(value); } remove { _rotateResizeDone.Remove(value); } }

        public void OnRotateOrResizeDone(ResizeInfo resizeInfo)
        {
            _rotateResizeDone.Raise(this, new ObjectEventArgs<FileImage, ResizeInfo>(this, resizeInfo));
        }

        public SingleThumbnail ThumbnailObject
        {
            get { return _ThumbnailObject; }
            set
            {
                if (_ThumbnailObject != value)
                {
                    if (_ThumbnailObject != null)
                    {
                        _ThumbnailObject.PropertyChanged -= _ThumbnailObject_PropertyChanged;
                        _ThumbnailObject.ThumbnailCached = null;
                    }

                    _ThumbnailObject = value;

                    if (_ThumbnailObject != null)
                    {
                        _ThumbnailObject.PropertyChanged += new PropertyChangedEventHandler(_ThumbnailObject_PropertyChanged);        
                    }
                    // OnPropertyChanged("ThumbnailObject");
                }
            }
        }

        public void OnThumbnailSet(SingleThumbnail thumb)
        {
            this.ThumbnailObject = thumb;

            if (ThumbnailCached != null)
            {
                if (Settings.Values.WantFilterThumbnails && Filters != null && Filters.Active && Filters.EnabledFiltersCount > 0)
                {
                    var bm = ThumbnailCached;
                    ThumbnailObject.SetFilteredThumbnail (Filters.Apply(FileName, bm, false));
                }
            }
        }
        
        void _ThumbnailObject_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            OnPropertyChangedUIThread(e.PropertyName);
        }

        public Bitmap PreloadThumbnail()
        {
            return ThumbnailProvider.PreloadThumbnail(this.FileName, this).ThumbnailCached;
        }

        public void ClearThumbnailSilently()
        {
            if (ThumbnailObject != null)
            {
                ThumbnailObject.ClearThumbnailSilently();
            }
        }

        public SingleThumbnail GetThumbnail(LoadOptions loadOptions, Action<FileImage, SingleThumbnail> callback, bool needThumbBytes = false)
        {
            var thumb = ThumbnailProvider.GetThumbnail(FileName, loadOptions, this, needThumbBytes, (o1, o2) => callback(o1 as FileImage, o2));
            this.ThumbnailObject = thumb;
            thumb.HasBitmap = this;
            return thumb;
        }

        public Bitmap Thumbnail
        {
            get
            {
                if (_deleted)
                {
                    Thumbnail = null;
                    return null;
                }

                if (ThumbnailObject == null)
                {
                    ThumbnailObject = ThumbnailProvider.GetThumbnail(FileName, LoadOptions.LoadSync, this, true, null);
                }

                return ThumbnailObject.ThumbnailCached;
            }
            set
            {
                HandleChangeThumbnailValue(value, true);
            }
        }

        public void ForceRelease(ReleaseOptions options)
        {
            SetSuspendPropertyChanged(true);

            if ((options & ReleaseOptions.Thumbnail) == ReleaseOptions.Thumbnail && ThumbnailObject != null)
            {
                ThumbnailObject = null;
            }
            if ((options & ReleaseOptions.ImageSource) == ReleaseOptions.ImageSource && _imageSource != null)
            {
                RecentlyUsedFileImages.RecentlyUsedImageSources.RemoveRecentlyUsed(this);
                ImageSource = null;
            }
            if ((options & ReleaseOptions.TransformedBitmap) == ReleaseOptions.TransformedBitmap && _transformedBitmap != null)
            {
                RecentlyUsedFileImages.RecentlyUsedTransformedBitmaps.RemoveRecentlyUsed(this);
                TransformedBitmap = null;
            }
            if ((options & ReleaseOptions.Bitmap) == ReleaseOptions.Bitmap && _bitmap != null)
            {
                RecentlyUsedFileImages.RecentlyUsedBitmaps.RemoveRecentlyUsed(this);
                Bitmap = null;

                // HEREHERE: test this
                if (_transformedBitmap != null)
                {
                    TransformedBitmap = null;
                }
            }
            if ((options & ReleaseOptions.FileBytes) == ReleaseOptions.FileBytes && _imageBytes != null)
            {
                RecentlyUsedFileImages.RecentlyUsedFileBytes.RemoveRecentlyUsed(this);
                _imageBytes = null;
            }

            SetSuspendPropertyChanged(false);
        }

        public void Release(ReleaseOptions options)
        {
            SetSuspendPropertyChanged(true);

            if ((options & ReleaseOptions.Thumbnail) == ReleaseOptions.Thumbnail && ThumbnailObject != null)
            {
                if (ThumbnailProvider.ThumbsInMemory.Count > ThumbnailProvider.TargetThumbs())
                {
                    ThumbnailObject = null;
                }
            }
            if ((options & ReleaseOptions.ImageSource) == ReleaseOptions.ImageSource && _imageSource != null)
            {
                if (FileImageCollection._latestCachedImageSources >= Settings.Values.MaxImageSourcesInMemory)
                {
                    RecentlyUsedFileImages.RecentlyUsedImageSources.RemoveRecentlyUsed(this);
                    ImageSource = null;
                    Interlocked.Decrement(ref FileImageCollection._latestCachedImageSources);
                }
            }
            if ((options & ReleaseOptions.TransformedBitmap) == ReleaseOptions.TransformedBitmap && _transformedBitmap != null)
            {
                RecentlyUsedFileImages.RecentlyUsedTransformedBitmaps.RemoveRecentlyUsed(this);
                TransformedBitmap = null;
            }
            if ((options & ReleaseOptions.Bitmap) == ReleaseOptions.Bitmap && _bitmap != null)
            {
                if (FileImageCollection._latestLoadedBitmapCount >= Settings.Values.MaxBitmapsInMemory)
                {
                    RecentlyUsedFileImages.RecentlyUsedBitmaps.RemoveRecentlyUsed(this);
                    Bitmap = null;

                    // HEREHERE: test this
                    if (_transformedBitmap != null)
                    {
                        TransformedBitmap = null;
                    }

                    Interlocked.Decrement(ref FileImageCollection._latestLoadedBitmapCount);
                }
            }
            if ((options & ReleaseOptions.FileBytes) == ReleaseOptions.FileBytes && _imageBytes != null)
            {
                if (FileImageCollection._latestLoadedFileCount >= Settings.Values.MaxFilesInMemory)
                {
                    RecentlyUsedFileImages.RecentlyUsedFileBytes.RemoveRecentlyUsed(this);
                    _imageBytes = null;
                    Interlocked.Decrement(ref FileImageCollection._latestLoadedFileCount);
                }
            }

            SetSuspendPropertyChanged(false);
        }

        public Bitmap ThumbnailCached
        {
            get
            {
                if (ThumbnailObject == null)
                {
                    return null;
                }

                return ThumbnailObject.ThumbnailCached;
            }
            set
            {
                HandleChangeThumbnailValue(value, false);
            }
        }

        protected void HandleChangeThumbnailValue(Bitmap newThumb, bool raiseOnThumbnailSet)
        {
            if (ThumbnailObject == null)
            {
                OnPropertyChanged("Thumbnail");                
                return;
            }

            ThumbnailObject.HandleChangeThumbnailValue(newThumb, raiseOnThumbnailSet);
        }

        public void OnThumbnailSet()
        {
            // _thumbnailSet.Raise(this, EventArgs.Empty);
            if (ThumbnailCached != null)
            {
                if (Settings.Values.WantFilterThumbnails && Filters != null && Filters.Active && Filters.EnabledFiltersCount > 0)
                {
                    var bm = ThumbnailCached;
                    ThumbnailCached = Filters.Apply(this._fileName, bm, false);
                }
            }
        }

        protected Bitmap HandleLoadThumbnail(Bitmap bm)
        {
            if (bm == null)
                return null;

            Debug.WriteLine("Rendered thumb for " + FileName);
            Bitmap bmOut;
            RenderSettings renderSettings;

            if (Settings.Values.HighQualityThumbs)
            {
                renderSettings = new RenderSettings()
                {
                    PixelFormat = Settings.Values.StandardColorPixelFormat,
                    Interpolation = Settings.Values.InterpolationMode,
                    Smoothing = Settings.Values.SmoothingMode,
                    RenderingMethod = Settings.Values.InternalRendering,
                    ForceHighQuality = Settings.Values.HighQualityThumbs
                };
            }
            else
            {
                renderSettings = Settings.Values.StandardRenderSettings;
            }

            bmOut = bm.ResizeBitmap(_originalBitmapWidth, _originalBitmapHeight, (int)Settings.Values.ThumbWidth, (int)Settings.Values.ThumbHeight, renderSettings);
            return bmOut;
        }
    }
}


//private void GetThumbnailOneWay()
//{
//    if (_thumbnail != null && !_thumbnailDirty)
//        return;

//    Bitmap bm = _bitmap;
//    if (bm != null && !_bitmapDirty)
//    {
//        Thumbnail = HandleLoadThumbnail(bm);
//    }
//    else
//    {
//        Thumbnail = HandleLoadThumbnail(ReadBitmapFromByteStream(EnsureImageBytesLoaded()));
//    }
//}
